using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Think.Problems;
using Think.Problems.Solitaire;

namespace Think.Test.Problems.Solitaire
{
    [TestClass]
    public class SolitaireStateTest
    {
        [TestMethod]
        public void ConstructSolitareState()
        {
            // Setup
            var state = new SolitaireState(0);
        }

        [TestMethod]
        public void ConstructSolitaireStateWith9Tableaus()
        {
            // Setup
            var state = new SolitaireState(0, 9);

            // Assert
            Assert.AreEqual(9, state.Tableaus.Length);
            Assert.AreEqual(1, state.Tableaus[0].Count);
            Assert.AreEqual(2, state.Tableaus[1].Count);
            Assert.AreEqual(3, state.Tableaus[2].Count);
            Assert.AreEqual(4, state.Tableaus[3].Count);
            Assert.AreEqual(5, state.Tableaus[4].Count);
            Assert.AreEqual(6, state.Tableaus[5].Count);
            Assert.AreEqual(7, state.Tableaus[6].Count);
            Assert.AreEqual(8, state.Tableaus[7].Count);
            Assert.AreEqual(9, state.Tableaus[8].Count);
        }

        [TestMethod]
        public void ConstructSolitareStateAndVerifyInitialState()
        {
            // Setup
            var state = new SolitaireState(1);

            // Assert
            Assert.AreEqual(4, state.Foundations.Length);
            Assert.IsNull(state.Foundations[0].TopCard);
            Assert.AreEqual(0, state.Foundations[0].Value);
            Assert.IsNull(state.Foundations[1].TopCard);
            Assert.AreEqual(0, state.Foundations[1].Value);
            Assert.IsNull(state.Foundations[2].TopCard);
            Assert.AreEqual(0, state.Foundations[2].Value);
            Assert.IsNull(state.Foundations[3].TopCard);
            Assert.AreEqual(0, state.Foundations[3].Value);

            foreach (var tableau in state.Tableaus)
            {
                Assert.IsNotNull(tableau.TopCard);
                Assert.IsTrue(Card.IsValid(tableau.TopCard));
            }

            Assert.IsNotNull(state.StockTop);
            Assert.IsTrue(Card.IsValid(state.StockTop));
        }

        [TestMethod]
        public void CloneSolitaireState()
        {
            // Setup
            var state = new SolitaireState(1, 9);

            // Execute
            var result = state.Clone();

            // Assert
            Assert.AreEqual(state.StockTop, result.StockTop);
            Assert.AreEqual(state.Tableaus.Length, result.Tableaus.Length);
            for (var i = 0; i < state.Tableaus.Length; i++)
            {
                Assert.AreEqual(state.Tableaus[i].Count, result.Tableaus[i].Count);
                Assert.AreEqual(state.Tableaus[i].FaceDownCount, result.Tableaus[i].FaceDownCount);
                Assert.AreEqual(state.Tableaus[i].FaceUpCount, result.Tableaus[i].FaceUpCount);
                CollectionAssert.AreEqual(state.Tableaus[i].FaceUp, result.Tableaus[i].FaceUp);
            }
        }

        [TestMethod]
        public void GetAvailableActions()
        {
            // Setup
            var state = new SolitaireState(123);

            // Execute
            var results = state.Actions();

            // Assert
            Assert.AreEqual(4, results.Length);
        }

    }
}